package com.tedu.ds.sessionAndMessage.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import com.tedu.ds.base.enmu.SessionStatus;
import com.tedu.ds.base.utils.CacheUtils;
import com.tedu.ds.sessionAndMessage.mapper.SessionAndMessageMapper;
import com.tedu.ds.sessionAndMessage.pojo.entity.Session;
import com.tedu.ds.sessionAndMessage.pojo.entity.WebMessage;
import com.tedu.ds.sessionAndMessage.rabbitMq.FanoutProducer;
import com.tedu.ds.sessionAndMessage.rabbitMq.Producer;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;


@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {

    @Autowired
    private SessionAndMessageMapper sessionAndMessageMapper;

    @Autowired
    private Producer producer;

    @Autowired
    private CacheUtils cacheUtils;

    @Autowired
    private FanoutProducer fanoutProducer;

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final ConcurrentHashMap<WebMessage, WebSocketSession> sessionMap=new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);

        System.out.println("连接成功");
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        super.handleMessage(session, message);
        String msg = message.getPayload().toString();
        WebMessage webMessage=objectMapper.readValue(msg,WebMessage.class);
        Session insertSession=new Session();
        if ("连接成功".equals(webMessage.getMessage())){
            if(webMessage.getSessionId()==null){
                if (webMessage.getCustId()!=null){
                    insertSession.setCustId(webMessage.getCustId());
                    List<Long> csIds = sessionAndMessageMapper.getCsId();
                    insertSession.setCsId(csIds.get(0));
                    sessionAndMessageMapper.insertSession(insertSession);
                    webMessage.setSessionId(insertSession.getId());
                    System.out.println("新建会话: "+insertSession);
                    String webMsg=objectMapper.writeValueAsString(webMessage);
                    session.sendMessage(new TextMessage(webMsg));
                    System.out.println("处理消息："+webMsg);
                }
            }
            Session updateSession=new Session();
            updateSession.setId(webMessage.getSessionId());
            updateSession.setStatus(SessionStatus.IN_PROGRESS.getCode());
            System.out.println(sessionAndMessageMapper);
            sessionAndMessageMapper.updateSession(updateSession);
            sessionMap.put(webMessage,session);
            System.out.println("当前存在的会话："+sessionMap);

        }else {
            // 广播消息
            fanoutProducer.fanoutMessage(msg);
        }


    }

    @RabbitListener(queues = "#{rabbitFanoutConfig.serverQueueName}",containerFactory = "deadLetterListenerContainerFactory",ackMode = "MANUAL")
    public void onFanout(Message message, com.rabbitmq.client.Channel channel)throws Exception{
        saveMessage(message, channel);
    }

    private void saveMessage(Message message, Channel channel) throws Exception {
        String jsonMessage = new String(message.getBody(), "UTF-8");  // 将消息体转换为字符串
        WebMessage webMessage = objectMapper.readValue(jsonMessage, WebMessage.class);  // 将字符串反序列化为 WebMessage 对象

        final Boolean[] t = {false};
        sessionMap.forEach((key, value) -> {
            WebMessage webMessage1 = key;
            System.out.println(webMessage1);
            if (webMessage.getSessionId().equals(webMessage1.getSessionId())) {
                if (webMessage.getCsId()==webMessage1.getCsId() || webMessage.getCustId()==webMessage1.getCustId()){
                    t[0] =true;
                }
                // 发送消息
                try {
                    value.sendMessage(new TextMessage(jsonMessage));
                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.out.println("会话 " + webMessage1.getSessionId() + ": " + (webMessage1.getCsName() != null ? webMessage1.getCsName() : webMessage1.getCustName()) + " 发送消息: " + jsonMessage);
            }
        });
        System.out.println("接收到消息"+jsonMessage);
        System.out.println(t[0]);
        if (t[0]){
            // 发送持久化的消息到 RabbitMQ
            System.out.println("---------------1");
            producer.sendMessage(jsonMessage);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }else {
            System.out.println("---------------2");
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        }
    }

    @RabbitListener(queues = "#{rabbitFanoutConfig.deadQueueName}",containerFactory = "deadLetterListenerContainerFactory",ackMode = "MANUAL")
    public void onDead(Message message, com.rabbitmq.client.Channel channel)throws Exception{
        saveMessage(message,channel);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        System.out.println("断开连接");

        // 安全地遍历并移除已关闭的会话
        sessionMap.forEach((key, value) -> {
            if (value.equals(session)) {
                sessionMap.remove(key);

                // 修改会话状态
                WebMessage end = (WebMessage) key;
                Session updateSession = new Session();
                updateSession.setId(end.getSessionId());
                updateSession.setEndTime(new Date());
                updateSession.setStatus(SessionStatus.CLOSED.getCode());
                sessionAndMessageMapper.updateSession(updateSession);
                System.out.println("更新会话信息: " + updateSession);
            }
        });

        // 可以在这里添加更多的清理工作，例如记录日志、释放资源等
        System.out.println("已从会话映射表中移除会话: " + session);
        System.out.println("当前存在的会话："+sessionMap);
    }




}
